package com.woniu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.client.ProductClient;
import com.woniu.commons.exception.VenueRuntimeException;
import com.woniu.commons.exception.YogaException;
import com.woniu.commons.model.RedisKey;
import com.woniu.commons.model.Result;
import com.woniu.commons.model.StateData;
import com.woniu.config.AlipayConfiguration;
import com.woniu.config.AlipayUtil;
import com.woniu.dao.mapper.YCourseOrderMapper;
import com.woniu.model.*;
import com.woniu.model.form.AddLeagueClassDetailForm;
import com.woniu.model.AddLeagueClassOrderPeopleForm;
import com.woniu.model.YLeagueClass;
import com.woniu.model.model.YCourseOrder;
import com.woniu.model.model.YGoodsItem;
import com.woniu.model.model.YGoodsOrder;
import com.woniu.model.model.YUserLeagueClassMargin;
import com.woniu.model.param.OrderPayParam;
import com.woniu.model.param.OrderPersonalClassParam;
import com.woniu.model.param.PagePayParam;
import com.woniu.service.YCourseOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.service.YLeagueClassDetailService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 胡歌
 * @since 2024年05月28日
 */
@Service
public class YCourseOrderServiceImpl extends ServiceImpl<YCourseOrderMapper, YCourseOrder> implements YCourseOrderService {

    @Resource
    private ProductClient productClient;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private AlipayUtil alipayUtil;

    @Resource
    private AlipayConfiguration alipayConfiguration;
    @Resource
    private YLeagueClassDetailService leagueClassDetailService;

    @Override
    public String orderLeagueClass(Integer userId, Integer leagueClassId) {

        RLock fairLock = redissonClient.getFairLock(RedisKey.orderLeagueClassClassId(leagueClassId));
        RLock fairLock1 = redissonClient.getFairLock(RedisKey.orderLeagueClassUserId(userId));

        RLock lock = redissonClient.getMultiLock(fairLock,fairLock1);

        String s;
        try {
            // 尝试获取锁，最多等待20s
            boolean success = lock.tryLock(20, TimeUnit.SECONDS);
            if (success) {
                YLeagueClass leagueClass = productClient.ByIdLeagueClass(leagueClassId).getData();
                System.out.println(leagueClass);
                if (leagueClass == null){
                    throw new YogaException(3101,"不存在该团课");
                }
                List<YCourseOrder> courseOrderList = baseMapper.selectList(new QueryWrapper<YCourseOrder>().eq("course_id", leagueClassId).ne("order_state", StateData.ORDER_STATE_CANCEL));
                if (courseOrderList.size()>=leagueClass.getPeopleNum()){
                    throw new YogaException(3202,"购买人数已满");
                }

                YCourseOrder courseOrder = new YCourseOrder();
                String orderNum = new Snowflake(1, 1).nextIdStr();

                courseOrder.setOrderNum(orderNum);
                courseOrder.setVenueId(leagueClass.getVenueId());
                courseOrder.setCourseId(leagueClassId);
                courseOrder.setOrderMoney(leagueClass.getPrice().multiply(new BigDecimal(leagueClass.getClassNum())));
                courseOrder.setFoundDate(LocalDateTime.now());
                courseOrder.setOrderState(StateData.ORDER_STATE_NOT_PAY);
                courseOrder.setClassType(1);
                courseOrder.setClassNum(leagueClass.getClassNum());
                courseOrder.setClassPrice(leagueClass.getPrice());
                courseOrder.setUserId(userId);

                baseMapper.insert(courseOrder);
                s = orderNum;
            } else {
                throw new Exception("服务器繁忙");
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //释放锁
            lock.unlock();
        }
        return s;




    }


    /**
     * 根据状态查询用户的订单
     * @param userId
     * @param orderState
     * @return
     */
    @Override
    public List<YCourseOrder> loadClassOrderByUserId(Integer userId,Integer orderState) {
        QueryWrapper<YCourseOrder> wrapper = new QueryWrapper<YCourseOrder>().eq("user_id", userId);
        if (orderState != null){
            if (orderState.equals(StateData.ORDER_STATE_NOT_PAY) || orderState.equals(StateData.ORDER_STATE_PAYED) ||orderState.equals(StateData.ORDER_STATE_CANCEL) || orderState.equals(StateData.ORDER_STATE_NOT_EVALUATE) || orderState.equals(StateData.ORDER_STATE_EVALUATE)){
                wrapper.eq("order_state",orderState);
            }

        }
        List<YCourseOrder> orders = baseMapper.selectList(wrapper);
        return orders;
    }

    @Override
    public String pay(OrderPayParam param) throws Exception {
        //1.检验传进来的参数是否正确
        QueryWrapper<YCourseOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("order_num",param.getOrderNum());
        YCourseOrder yGoodsOrder = baseMapper.selectOne(wrapper);
        if (yGoodsOrder==null|| !Objects.equals(yGoodsOrder.getOrderNum(), param.getOrderNum())){
            throw new YogaException(500,"订单不存在");
        }
        if (!Objects.equals(yGoodsOrder.getOrderState(), StateData.ORDER_STATE_NOT_PAY)){
            throw new YogaException(500,"订单状态异常");
        }
        //2.组装参数
        PagePayParam payParam = new PagePayParam();
        payParam.setBody("yogo订单支付");
        payParam.setMoney(yGoodsOrder.getOrderMoney().doubleValue());
        payParam.setNotifyUrl("http://udcn8h.natappfree.cc/order/yCourseOrder/notify");
        payParam.setReturnUrl("http://localhost:9091/#/UserMyOrder");
        payParam.setOrderId(yGoodsOrder.getOrderNum());
        payParam.setSubject("yoga");
        //取出数据库订单的下单时间
        long expireTime = Date.from(yGoodsOrder.getFoundDate().plusMinutes(15).atZone(ZoneId.systemDefault()).toInstant()).getTime();
        long now = new Date().getTime();
        int minute = (int)((expireTime - now)/1000/60);
        if (minute<1){
            yGoodsOrder.setOrderState(StateData.ORDER_STATE_CANCEL);
            baseMapper.updateById(yGoodsOrder);
            throw new YogaException(500,"订单超时");
        }
        Date date = new Date(expireTime);
        String expire = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        payParam.setTimeExpire(expire);//可支付的时间
        //调用支付宝工具类
        String s = alipayUtil.pagePay(payParam);
        return s;
    }

    /**
     * 支付回调
     * @param map
     * @throws AlipayApiException
     */
    @Override
    public void payNotify(Map<String, String> map) throws AlipayApiException {
        boolean signVerified = AlipaySignature.rsaCheckV1(map, alipayConfiguration.getAlipayPublicKey(), "utf-8", "RSA2");
        if (signVerified) {
            //验签成功

            String orderNum = map.get("out_trade_no");
            String status = map.get("trade_status");

            if ("TRADE_SUCCESS".equals(status)){
                //支付成功
                //修改订单状态为支付
                QueryWrapper<YCourseOrder> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("order_num",orderNum);
                YCourseOrder yGoodsOrder = baseMapper.selectOne(queryWrapper);

                if (Objects.equals(yGoodsOrder.getOrderState(), StateData.ORDER_STATE_NOT_PAY)) {
                    //如果订单状态是未支付才进下一步操作
                    yGoodsOrder.setOrderState(StateData.ORDER_STATE_PAYED);
                    String payTimeStr = map.get("gmt_payment");
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                    LocalDateTime parse = LocalDateTime.parse(payTimeStr, formatter);
                    yGoodsOrder.setFinishTime(parse);

                    baseMapper.updateById(yGoodsOrder);

                    if (yGoodsOrder.getClassType().equals(1)){
                        productClient.addLeagueClassOrderPeople(new AddLeagueClassOrderPeopleForm(yGoodsOrder.getCourseId(), yGoodsOrder.getUserId(), yGoodsOrder.getOrderNum()));

                        productClient.addLeagueClassMargin(new AddLeagueClassMarginForm(orderNum,yGoodsOrder.getCourseId(), yGoodsOrder.getUserId(), yGoodsOrder.getClassNum(), null));

                        List<YLeagueWorkforce> leagueWorkforces = productClient.loadLeagueWorkforceByClassId(yGoodsOrder.getCourseId()).getData();
                        if (leagueWorkforces.size()!=0){
                            for (YLeagueWorkforce l: leagueWorkforces
                                 ) {
                                AddLeagueClassDetailForm form = new AddLeagueClassDetailForm();
                                form.setStartTime(l.getStartTime());
                                form.setEndTime(l.getEndTime());
                                form.setCoachId(l.getCoachId());

                                ArrayList<YUserLeagueClassMargin> margins = new ArrayList<>();
                                margins.add(BeanUtil.toBean(productClient.loadLeagueClassMarginByOrderNum(orderNum).getData(),YUserLeagueClassMargin.class));
                                form.setMargins(margins);
                                form.setLeagueClassId(l.getLeagueClassId());
                                form.setLeagueClassWorkforceId(l.getId());


                                leagueClassDetailService.addLeagueClassDetail(form);
                            }
                        }
                    }else {
                        productClient.addPersonalClassMargin(new AddPersonalClassMarginForm(orderNum, yGoodsOrder.getCourseId(), yGoodsOrder.getUserId(), yGoodsOrder.getClassNum()));



                    }


                }
            }
        }
    }

    @Override
    public String orderPersonalClass(OrderPersonalClassParam param) {

        RLock fairLock = redissonClient.getFairLock(RedisKey.orderPersonalClassClassId(param.getPersonalClassId()));

        RLock lock = redissonClient.getMultiLock(fairLock);

        String s ;
        try {
            // 尝试获取锁，最多等待20s
            boolean success = lock.tryLock(20, TimeUnit.SECONDS);
            if (success) {

                YPersonalClass personalClass = productClient.byIdPersonal(param.getPersonalClassId()).getData();
                if (personalClass == null){
                    throw new YogaException(3101,"不存在该私教课");
                }


                YCourseOrder courseOrder = new YCourseOrder();
                String orderNum = new Snowflake(1, 1).nextIdStr();
                courseOrder.setOrderNum(orderNum);
                courseOrder.setCourseId(personalClass.getPersonalClassId());
                courseOrder.setOrderMoney(personalClass.getPrice().multiply(new BigDecimal(param.getClassNum())));
                courseOrder.setFoundDate(LocalDateTime.now());
                courseOrder.setOrderState(StateData.ORDER_STATE_NOT_PAY);
                courseOrder.setClassType(2);
                courseOrder.setClassNum(param.getClassNum());
                courseOrder.setClassPrice(personalClass.getPrice());
                courseOrder.setUserId(param.getUserId());

                baseMapper.insert(courseOrder);

                s = orderNum;
            } else {
                throw new Exception("服务器繁忙");
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //释放锁
            lock.unlock();
        }
        return s;

    }
}
